#pragma once

#include "isingleton.h"
#include "Application.h"
#include "ClockListener.h"
#include "ClockSource.h"
#include "Window.h"
#include "mutievent.h"

#include <vector>
typedef struct IDirectInputDevice8 *LPDIRECTINPUTDEVICE8;

class KeyboardListener;
struct KeyboardEvent
{
public:
	bool keyMap[256];
	vector<unsigned long> keyJustPress;
	vector<unsigned long> keyJustRelease;
};
class KeyboardSource :
	public MutiSource<KeyboardSource,KeyboardListener,3,KeyboardEvent>,public ISingleton<KeyboardSource,Window>,public Clock::ClockListener
{
	LPDIRECTINPUTDEVICE8 lpKeyboard;
	KeyboardEvent m;
	int nKeyPressing;

public:
	enum {DOWN,UP,PRESSING} ;
	void AddDownHandle(KeyboardListener* downListener);
	void AddUpHandle(KeyboardListener* upListener);
	void AddPressingHandle(KeyboardListener* pressingListener);
	KeyboardEvent& getEvent();
	KeyboardSource(Window& win);
	virtual void OnClock(Clock::ClockListener::SourceType& t);
public:
	~KeyboardSource(void);
};


/****************************************************************************
 *
 *      DirectInput keyboard scan codes
 *
 ****************************************************************************/
#define K_ESCAPE          0x01
#define K_1               0x02
#define K_2               0x03
#define K_3               0x04
#define K_4               0x05
#define K_5               0x06
#define K_6               0x07
#define K_7               0x08
#define K_8               0x09
#define K_9               0x0A
#define K_0               0x0B
#define K_MINUS           0x0C    /* - on main keyboard */
#define K_EQUALS          0x0D
#define K_BACK            0x0E    /* backspace */
#define K_TAB             0x0F
#define K_Q               0x10
#define K_W               0x11
#define K_E               0x12
#define K_R               0x13
#define K_T               0x14
#define K_Y               0x15
#define K_U               0x16
#define K_I               0x17
#define K_O               0x18
#define K_P               0x19
#define K_LBRACKET        0x1A
#define K_RBRACKET        0x1B
#define K_RETURN          0x1C    /* Enter on main keyboard */
#define K_LCONTROL        0x1D
#define K_A               0x1E
#define K_S               0x1F
#define K_D               0x20
#define K_F               0x21
#define K_G               0x22
#define K_H               0x23
#define K_J               0x24
#define K_K               0x25
#define K_L               0x26
#define K_SEMICOLON       0x27
#define K_APOSTROPHE      0x28
#define K_GRAVE           0x29    /* accent grave */
#define K_LSHIFT          0x2A
#define K_BACKSLASH       0x2B
#define K_Z               0x2C
#define K_X               0x2D
#define K_C               0x2E
#define K_V               0x2F
#define K_B               0x30
#define K_N               0x31
#define K_M               0x32
#define K_COMMA           0x33
#define K_PERIOD          0x34    /* . on main keyboard */
#define K_SLASH           0x35    /* / on main keyboard */
#define K_RSHIFT          0x36
#define K_MULTIPLY        0x37    /* * on numeric keypad */
#define K_LMENU           0x38    /* left Alt */
#define K_SPACE           0x39
#define K_CAPITAL         0x3A
#define K_F1              0x3B
#define K_F2              0x3C
#define K_F3              0x3D
#define K_F4              0x3E
#define K_F5              0x3F
#define K_F6              0x40
#define K_F7              0x41
#define K_F8              0x42
#define K_F9              0x43
#define K_F10             0x44
#define K_NUMLOCK         0x45
#define K_SCROLL          0x46    /* Scroll Lock */
#define K_NUMPAD7         0x47
#define K_NUMPAD8         0x48
#define K_NUMPAD9         0x49
#define K_SUBTRACT        0x4A    /* - on numeric keypad */
#define K_NUMPAD4         0x4B
#define K_NUMPAD5         0x4C
#define K_NUMPAD6         0x4D
#define K_ADD             0x4E    /* + on numeric keypad */
#define K_NUMPAD1         0x4F
#define K_NUMPAD2         0x50
#define K_NUMPAD3         0x51
#define K_NUMPAD0         0x52
#define K_DECIMAL         0x53    /* . on numeric keypad */
#define K_OEM_102         0x56    /* <> or \| on RT 102-key keyboard (Non-U.S.) */
#define K_F11             0x57
#define K_F12             0x58
#define K_F13             0x64    /*                     (NEC PC98) */
#define K_F14             0x65    /*                     (NEC PC98) */
#define K_F15             0x66    /*                     (NEC PC98) */
#define K_KANA            0x70    /* (Japanese keyboard)            */
#define K_ABNT_C1         0x73    /* /? on Brazilian keyboard */
#define K_CONVERT         0x79    /* (Japanese keyboard)            */
#define K_NOCONVERT       0x7B    /* (Japanese keyboard)            */
#define K_YEN             0x7D    /* (Japanese keyboard)            */
#define K_ABNT_C2         0x7E    /* Numpad . on Brazilian keyboard */
#define K_NUMPADEQUALS    0x8D    /* = on numeric keypad (NEC PC98) */
#define K_PREVTRACK       0x90    /* Previous Track (K_CIRCUMFLEX on Japanese keyboard) */
#define K_AT              0x91    /*                     (NEC PC98) */
#define K_COLON           0x92    /*                     (NEC PC98) */
#define K_UNDERLINE       0x93    /*                     (NEC PC98) */
#define K_KANJI           0x94    /* (Japanese keyboard)            */
#define K_STOP            0x95    /*                     (NEC PC98) */
#define K_AX              0x96    /*                     (Japan AX) */
#define K_UNLABELED       0x97    /*                        (J3100) */
#define K_NEXTTRACK       0x99    /* Next Track */
#define K_NUMPADENTER     0x9C    /* Enter on numeric keypad */
#define K_RCONTROL        0x9D
#define K_MUTE            0xA0    /* Mute */
#define K_CALCULATOR      0xA1    /* Calculator */
#define K_PLAYPAUSE       0xA2    /* Play / Pause */
#define K_MEDIASTOP       0xA4    /* Media Stop */
#define K_VOLUMEDOWN      0xAE    /* Volume - */
#define K_VOLUMEUP        0xB0    /* Volume + */
#define K_WEBHOME         0xB2    /* Web home */
#define K_NUMPADCOMMA     0xB3    /* , on numeric keypad (NEC PC98) */
#define K_DIVIDE          0xB5    /* / on numeric keypad */
#define K_SYSRQ           0xB7
#define K_RMENU           0xB8    /* right Alt */
#define K_PAUSE           0xC5    /* Pause */
#define K_HOME            0xC7    /* Home on arrow keypad */
#define K_UP              0xC8    /* UpArrow on arrow keypad */
#define K_PRIOR           0xC9    /* PgUp on arrow keypad */
#define K_LEFT            0xCB    /* LeftArrow on arrow keypad */
#define K_RIGHT           0xCD    /* RightArrow on arrow keypad */
#define K_END             0xCF    /* End on arrow keypad */
#define K_DOWN            0xD0    /* DownArrow on arrow keypad */
#define K_NEXT            0xD1    /* PgDn on arrow keypad */
#define K_INSERT          0xD2    /* Insert on arrow keypad */
#define K_DELETE          0xD3    /* Delete on arrow keypad */
#define K_LWIN            0xDB    /* Left Windows key */
#define K_RWIN            0xDC    /* Right Windows key */
#define K_APPS            0xDD    /* AppMenu key */
#define K_POWER           0xDE    /* System Power */
#define K_SLEEP           0xDF    /* System Sleep */
#define K_WAKE            0xE3    /* System Wake */
#define K_WEBSEARCH       0xE5    /* Web Search */
#define K_WEBFAVORITES    0xE6    /* Web Favorites */
#define K_WEBREFRESH      0xE7    /* Web Refresh */
#define K_WEBSTOP         0xE8    /* Web Stop */
#define K_WEBFORWARD      0xE9    /* Web Forward */
#define K_WEBBACK         0xEA    /* Web Back */
#define K_MYCOMPUTER      0xEB    /* My Computer */
#define K_MAIL            0xEC    /* Mail */
#define K_MEDIASELECT     0xED    /* Media Select */

/*
 *  Alternate names for keys, to facilitate transition from DOS.
 */
#define K_BACKSPACE       K_BACK            /* backspace */
#define K_NUMPADSTAR      K_MULTIPLY        /* * on numeric keypad */
#define K_LALT            K_LMENU           /* left Alt */
#define K_CAPSLOCK        K_CAPITAL         /* CapsLock */
#define K_NUMPADMINUS     K_SUBTRACT        /* - on numeric keypad */
#define K_NUMPADPLUS      K_ADD             /* + on numeric keypad */
#define K_NUMPADPERIOD    K_DECIMAL         /* . on numeric keypad */
#define K_NUMPADSLASH     K_DIVIDE          /* / on numeric keypad */
#define K_RALT            K_RMENU           /* right Alt */
#define K_UPARROW         K_UP              /* UpArrow on arrow keypad */
#define K_PGUP            K_PRIOR           /* PgUp on arrow keypad */
#define K_LEFTARROW       K_LEFT            /* LeftArrow on arrow keypad */
#define K_RIGHTARROW      K_RIGHT           /* RightArrow on arrow keypad */
#define K_DOWNARROW       K_DOWN            /* DownArrow on arrow keypad */
#define K_PGDN            K_NEXT            /* PgDn on arrow keypad */

/*
 *  Alternate names for keys originally not used on US keyboards.
 */
#define K_CIRCUMFLEX      K_PREVTRACK       /* Japanese keyboard */
